#pragma once
 
#include "Windows.h"
#include <string>
#include <queue>

class WorkQueue;
 
class WorkItemBase
{
   virtual void work(void* context)    = 0;
   virtual void abort () = 0;
   friend WorkQueue;
};
 
typedef std::queue<WorkItemBase*> WorkItemQueue, *PWorkItemQueue;
 
class  WorkQueue {
public:
	virtual ~WorkQueue() {};
	bool create(const unsigned int num_of_threads, void** thread_data_array = NULL);
	bool insert_work_item(WorkItemBase* work_iterm);
	void destroy(int wait_seconds = 1);
	int get_threads_num();
	void suspend();
	void resume();
public:
	PHANDLE threads_;
private:
	static unsigned long __stdcall thread_func(void* param);
	WorkItemBase* remove_work_item();
	size_t get_work_queue_size();

	enum {
		ABORT_EVENT_INDEX = 0,
		SEMAPHORE_INDEX,
		NUMBER_OF_SYNC_OBJ,
	};

	unsigned int num_of_threads_;
	void* thread_data_array_;
	HANDLE sync_obj_array_[NUMBER_OF_SYNC_OBJ];

	CRITICAL_SECTION cs_;
	PWorkItemQueue work_item_queue_;
};
 

